package belajarzk.common;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.Serializable;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Properties;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import org.apache.log4j.Logger;
import org.hibernate.Criteria;
import org.hibernate.EntityMode;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Restrictions;
import org.hibernate.metadata.ClassMetadata;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.Sessions;
import org.zkoss.zul.Bandbox;
import org.zkoss.zul.Combobox;
import org.zkoss.zul.Comboitem;
import org.zkoss.zul.Decimalbox;
import org.zkoss.zul.Messagebox;
import org.zkoss.zul.Textbox;
import org.zkoss.zul.Tree;
import org.zkoss.zul.Treechildren;
import org.zkoss.zul.Treeitem;

import belajarzk.database.hibernate.HibernateUtil;
import belajarzk.database.model.CommonVO;
import belajarzk.database.model.Menu;
import belajarzk.database.model.Tbmuser;
import belajarzk.ui.util.MyDatebox;


public class Common {

	private static Logger log = Logger.getLogger(Common.class);

	public static String ROOT = "/bnn";
	public static SimpleDateFormat dateFormat = new SimpleDateFormat(
			"dd-MM-yyyy HH:mm");
	public static SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm:ss");
	public static NumberFormat numberFormat = NumberFormat
			.getNumberInstance(new Locale("in", "ID"));
	public static int MAX_RESULT = 300;
	public static String ROOT_UPLOAD;

	public static String[] haris = { "Senin", "Selasa", "Rabu", "Kamis",
			"Jum'at", "Sabtu", "Minggu" };

	public static Locale locale = new Locale("in", "ID");
	public static Locale localeEn = Locale.US;

	private static boolean hasInitialQuery = false;

	private static Long autoGeneratorId = 0L;

	public static String getGeneratedCode() {
		String str = "" + Calendar.getInstance().getTimeInMillis() + ""
				+ (++autoGeneratorId);
		Long lg = Long.parseLong(str);
		return Long.toHexString(lg).toUpperCase();
	}

	// public static void saveLogTrackingHistory(
	// Tpengirimandetil tpengirimandetil,
	// Tdeliveryexception tdeliveryexception, String keterangan) {
	// LogTrackingHistory trackingHistory = new LogTrackingHistory();
	// trackingHistory.setKeterangan(keterangan);
	// trackingHistory.setTanggal(new Date());
	// trackingHistory.setMagen(getCurrentUser().getMagen());
	// trackingHistory.setTpengirimandetil(tpengirimandetil);
	// trackingHistory.setTdeliveryexception(tdeliveryexception);
	// Session session = HibernateUtil.currentSession();
	// 
	// session.save(trackingHistory);
	// 
	// }

	public static Criterion createBetween(String att, MyDatebox tanggal,
			MyDatebox tanggal1) {
		Criterion criterion = Restrictions.sqlRestriction("1=1");
		if (tanggal.getValue() != null && tanggal1.getValue() != null) {
			Date date1 = tanggal.getValue();
			Date date2 = tanggal1.getValue();
			Calendar calendar1 = Calendar.getInstance();
			calendar1.setTime(date1);
			calendar1.set(Calendar.HOUR_OF_DAY, 0);
			calendar1.set(Calendar.MINUTE, 0);
			calendar1.set(Calendar.SECOND, 0);
			Calendar calendar2 = Calendar.getInstance();
			calendar2.setTime(date2);
			calendar2.set(Calendar.HOUR_OF_DAY, 24);
			calendar2.set(Calendar.MINUTE, 0);
			calendar2.set(Calendar.SECOND, 0);
			criterion = Restrictions.between(att, calendar1.getTime(),
					calendar2.getTime());
		} else if (tanggal.getValue() != null) {
			Date date1 = tanggal.getValue();
			Calendar calendar1 = Calendar.getInstance();
			calendar1.setTime(date1);
			calendar1.set(Calendar.HOUR_OF_DAY, 0);
			calendar1.set(Calendar.MINUTE, 0);
			calendar1.set(Calendar.SECOND, 0);
			criterion = Restrictions.ge(att, calendar1.getTime());
		} else if (tanggal1.getValue() != null) {
			Date date2 = tanggal1.getValue();
			Calendar calendar2 = Calendar.getInstance();
			calendar2.setTime(date2);
			calendar2.set(Calendar.HOUR_OF_DAY, 24);
			calendar2.set(Calendar.MINUTE, 0);
			calendar2.set(Calendar.SECOND, 0);
			criterion = Restrictions.le(att, calendar2.getTime());
		}
		return criterion;
	}

	public static String getGeneratedBarCode() {
		String str = "" + Calendar.getInstance().getTimeInMillis() + ""
				+ (++autoGeneratorId);
		return str;
	}

	static {
		numberFormat.setMaximumFractionDigits(2);
	}

	public static Tbmuser getCurrentUser() {
		Tbmuser users = (Tbmuser) Sessions.getCurrent().getAttribute(
				"usersTemp");
		return users;
	}

	public static Combobox generateJam(Combobox combobox) {
		if (combobox == null) {
			combobox = new Combobox();
		}

		return combobox;
	}

	public static String generateSingkatan(String asal) {
		if (asal == null || asal.trim().equals("")) {
			return "";
		}
		String[] ss = asal.split(" ");
		String hasil = "";
		for (String s : ss) {
			if (s.trim().equals(""))
				continue;
			hasil += s.trim().substring(0, 1).toUpperCase();
		}
		return hasil;
	}

	public static Combobox generateTahunAjaran(Combobox combobox) {
		if (combobox == null) {
			combobox = new Combobox();
		}
		String current = "";
		if (Calendar.getInstance().get(Calendar.MONTH) > 6) {
			current = Calendar.getInstance().get(Calendar.YEAR) + "/"
					+ (Calendar.getInstance().get(Calendar.YEAR) + 1);
		} else {
			current = (Calendar.getInstance().get(Calendar.YEAR) - 1) + "/"
					+ (Calendar.getInstance().get(Calendar.YEAR));
		}

		for (Integer i = Calendar.getInstance().get(Calendar.YEAR) + 5; i >= Calendar
				.getInstance().get(Calendar.YEAR) - 20; i--) {
			String value = (i - 1) + "/" + (i);
			Comboitem comboitem = new Comboitem();
			comboitem.setLabel(value);
			comboitem.setValue(value);
			combobox.appendChild(comboitem);
		}
		selectComboItem(combobox, current);
		return combobox;
	}

	@SuppressWarnings("unchecked")
	public static Boolean isMenuExist(Tree tree, Menu menu) {
		List child = tree.getChildren();
		for (Object o : child) {
			System.out.println(o.getClass().getName());
			if (o instanceof Treechildren) {
				Treechildren treechildren = (Treechildren) o;
				List<Treeitem> treeitems = treechildren.getChildren();
				for (Treeitem treeitem : treeitems) {
					if (menu.getUrl() != null && treeitem.getValue() != null
							&& menu.getUrl().trim().equals(treeitem.getValue())) {
						return true;
					}
				}
			}
		}
		return false;
	}

	public static Boolean isMenuExist(Collection<Menu> menus, Menu menu) {

		for (Menu my : menus) {
			if (menu.getUrl() != null && my.getUrl() != null
					&& menu.getUrl().trim().equals(my.getUrl().trim())) {
				return true;
			}
		}

		return false;
	}

	public static Tbmuser getTbmuser() {
		return (Tbmuser) Sessions.getCurrent().getAttribute("users");
	}

	@SuppressWarnings("unchecked")
	public static void initCombos(Combobox[] comboboxs, String[] properties,
			Class[] classes) {
		for (Integer i = 0; i < comboboxs.length; i++) {
			insertCombo(comboboxs[i], properties[i], classes[i]);
		}
	}

	@SuppressWarnings("unchecked")
	public static void initCombos(Combobox[] comboboxs, String[] properties,
			Class[] classes, Criterion[] criterions) {
		for (Integer i = 0; i < comboboxs.length; i++) {
			insertCombo(comboboxs[i], properties[i], classes[i], criterions[i]);
		}
	}

	@SuppressWarnings("unchecked")
	public static void insertCombo(Combobox combobox, String property,
			Class clazz, Criterion... criterions) {
		Criteria criteria = HibernateUtil.currentSession()
				.createCriteria(clazz);
		if (criterions != null) {
			for (Criterion criterion : criterions) {
				if (criterion != null) {
					criteria.add(criterion);
				}
			}
		}
		List list = criteria.list();
		insertComboItems(combobox, property, list);
	}

	@SuppressWarnings("unchecked")
	public static void insertCombo(Combobox combobox, String property,
			Class clazz) {
		if (combobox == null)
			return;
		Criteria criteria = HibernateUtil.currentSession()
				.createCriteria(clazz);

		List list = criteria.list();
		insertComboItems(combobox, property, list);
	}

	public static Boolean checkValidasi(Object... property) throws Exception {
		for (Object o : property) {
			if (o instanceof String) {
				if (o == null || o.toString().trim().equals("")) {
					Messagebox.show("Field harus dilengkapi");
					return false;
				}
			}
			if (o instanceof Textbox) {
				Textbox oo = (Textbox) o;
				if (oo.getValue().trim().equals("")) {
					Messagebox.show("Field ini harus diisi");
					oo.focus();
					return false;
				}
			}
			if (o instanceof Bandbox) {
				Bandbox oo = (Bandbox) o;
				if (oo.getValue().trim().equals("")) {
					Messagebox.show("Field ini harus diisi");
					oo.focus();
					return false;
				}
			}
			if (o instanceof Combobox) {
				Combobox oo = (Combobox) o;
				if (oo.getSelectedItem() == null
						|| oo.getSelectedItem().getValue() == null) {
					Messagebox.show("Field ini harus diisi");
					oo.focus();
					return false;
				}
			}

			if (o instanceof Decimalbox) {
				Decimalbox oo = (Decimalbox) o;
				if (oo.getValue() == null || oo.getValue().equals("")) {
					Messagebox.show("Field ini harus diisi");
					oo.focus();
					return false;
				}
			}

		}
		return true;
	}

	public static void clear(Component comp) {
		if (comp == null || comp.getChildren() == null)
			return;
		int list = comp.getChildren().size();
		for (Integer i = 0; i < list; i++) {
			((Component) comp.getChildren().get(0)).detach();
		}
	}

	@SuppressWarnings("unchecked")
	public static void insertComboItems(Combobox combo, String property,
			List items) {
		Common.clear(combo);
		if (items.size() == 0)
			return;
		Class clazz = items.get(0).getClass();
		ClassMetadata metadata = null;
		if (!clazz.equals(CommonVO.class)) {
			metadata = HibernateUtil.getClassMetadata(clazz);
		}
		for (Object o : items) {
			Comboitem comboitem = new Comboitem();
			if (o instanceof CommonVO) {
				CommonVO oo = (CommonVO) o;
				comboitem.setLabel(oo.getName());
				comboitem.setValue(oo.getId());
			} else {
				comboitem.setLabel(property.equals("") ? o + "" : ""
						+ metadata.getPropertyValue(o, property,
								EntityMode.POJO));
				comboitem.setValue(o);
			}
			combo.appendChild(comboitem);
		}
	}

	@SuppressWarnings("unchecked")
	public static void selectComboItem(Combobox combo, Object value) {
		if (value == null) {
			combo.setSelectedItem(null);
			return;
		}

		List<Comboitem> list = combo.getItems();
		ClassMetadata metadata = HibernateUtil.getClassMetadata(value
				.getClass());
		Serializable identityvalue = null;
		if (!(value instanceof String) && !(value instanceof Integer)
				&& !(value instanceof Double) && !(value instanceof Date)) {
			try {
				identityvalue = metadata.getIdentifier(value, EntityMode.POJO);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}

		for (Comboitem comboitem : list) {
			if ((value instanceof String) || (value instanceof Integer)
					|| (value instanceof Double) || (value instanceof Date)) {
				// System.out.println("value = " + value
				// + ", comboitem.getValue() = " + comboitem.getValue());
				if (value.equals(comboitem.getValue())) {
					combo.setSelectedItem(comboitem);
				}
			} else {
				try {
					Serializable id = metadata.getIdentifier(comboitem
							.getValue(), EntityMode.POJO);
					// System.out.println("identityvalue = " + identityvalue
					// + ", id = " + id);

					if (identityvalue.equals(id)) {
						combo.setSelectedItem(comboitem);
					}
				} catch (Exception e) {
				}
			}
		}
	}

	public static Boolean createZip(List<String> filesName,
			List<File> filenames, File outFilename) {
		if (filenames.size() == 0) {
			return false;
		}
		// These are the files to include in the ZIP file

		// Create a buffer for reading the files
		byte[] buf = new byte[1024];

		try {
			outFilename.createNewFile();
			// Create the ZIP file
			ZipOutputStream out = new ZipOutputStream(new FileOutputStream(
					outFilename));

			int i = 0;
			// Compress the files
			for (File filename : filenames) {
				FileInputStream in = new FileInputStream(filename);

				// Add ZIP entry to output stream.
				out.putNextEntry(new ZipEntry(filesName.get(i)));

				// Transfer bytes from the file to the ZIP file
				int len;
				while ((len = in.read(buf)) > 0) {
					out.write(buf, 0, len);
				}

				// Complete the entry
				out.closeEntry();
				in.close();
				i++;
			}

			// Complete the ZIP file
			out.close();
		} catch (IOException e) {
			e.printStackTrace();
			return false;
		}
		return true;
	}

	public static void executeInitialQuery() {
		if (hasInitialQuery)
			return;

		log
				.info("execute Initial Query ...........................................");

		Session session = HibernateUtil.currentSession();

		String sql = "set global transaction isolation level read committed;";
		session.createSQLQuery(sql).executeUpdate();

		sql = "set session transaction isolation level read committed;";
		session.createSQLQuery(sql).executeUpdate();

		sql = "SELECT @@global.tx_isolation;";
		session.createSQLQuery(sql).list();

		sql = "SELECT @@tx_isolation;";
		session.createSQLQuery(sql).list();

		List<String> quries = new ArrayList<String>();
		quries.add("create table judisium ( " + "id double , "
				+ "judisium varchar (255), " + "nilai_mulai double , "
				+ "nilai_sampai double  " + ")");

		quries
				.add("insert into judisium (id, judisium, nilai_mulai, nilai_sampai) values('1','Buruk','0.0000','2.7499')");
		quries
				.add("insert into judisium (id, judisium, nilai_mulai, nilai_sampai) values('2','Sangat Memuaskan','2.7500','3.4999')");
		quries
				.add("insert into judisium (id, judisium, nilai_mulai, nilai_sampai) values('3','Cumlaude','3.5000','4.0000')");

		for (String q : quries) {
			try {
				int i = session.createSQLQuery(q).executeUpdate();
				log.info("result = " + i);
			} catch (HibernateException e) {
				// TODO Auto-generated catch block
				// e.printStackTrace();
			}
		}

		hasInitialQuery = true;
	}

	@SuppressWarnings("unchecked")
	public static void realodBahasa() {
		Locale localeEn = Common.localeEn;
		Locale localeId = Common.locale;
		Tbmuser tbmuser = getCurrentUser();
		if (tbmuser.getBahasa() == null) {
			tbmuser.setBahasa(localeId.getCountry());
			Session session = HibernateUtil.currentSession();

			session.update(session.merge(tbmuser));

		}

		Properties properties = System.getProperties();
		Session session = HibernateUtil.currentSession();

		System.setProperties(properties);
	}

	public static String getBahasa(String key) {
		try {
			Properties properties = System.getProperties();
			Tbmuser tbmuser = getCurrentUser();
			String bahasa = tbmuser.getBahasa();
			System.out.println("locale = " + bahasa);
			return properties.getProperty(key + "_" + bahasa);
		} catch (Exception e) {
			// e.printStackTrace();
			return "[" + key.replaceAll("_", " ") + "]";
		}
	}

}
